package org.exussum0.eyecks1;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
 * A simple class resolver given a set of packages for an unqualified clasname.
 * Do not trust this if a magical class loader will decide between two different
 * implementations of the same class in the same package.
 */
public class ClassResolver {

	private Set<String> includes = new HashSet<String>();

	/**
	 * Set of packages to inspect.
	 */
	public void setIncludes(Set<String> includes) {
		this.includes = includes;
	}

	public String getPackage(String classname) {
		Class<?> clazz = getClass(classname);
		return clazz == null ? null : clazz.getPackage().toString();
	}

	/**
	 * Given a classname, attempt to find the fully qualified class, including
	 * its package name.
	 * 
	 * @param imports
	 *            A collection of imports to check.
	 * @param className
	 *            The class name to attempt to find. If this is fully qualified,
	 *            it will only check the classloader to see if it exists.
	 * @return A class with its package name or null if none are found. This
	 *         results when the class name is wrong, the imports are wrong or
	 *         the class is not in the classloader.
	 */
	public String resolve(Collection<String> imports, String className)
			throws ClassNotFoundException {
		// Try no import checking
		if (classResolves(className))
			return className;

		// Try import checking
		String dotted = "." + className;
		for (String imported : imports) {
			boolean found = false;
			for (String included : includes) {
				if (imported.startsWith(included))
					found = true;
			}
			if (includes != null && !includes.isEmpty() && !found)
				continue;

			if (imported.endsWith(dotted))
				return imported;

			if (imported.endsWith("*")) {
				imported = imported.replaceAll("\\*", className);
				if (classResolves(imported))
					return imported;
			}
		}
		return null;
	}

	public Class getClass(String className) {
		try {
			return getClass().getClassLoader().loadClass(className);
		} catch (ClassNotFoundException e) {
		} catch (NoClassDefFoundError e) {
		}
		return null;
	}

	private boolean classResolves(String className) {
		return getClass(className) != null;
	}

}
